package com.tang.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tang.dto.UserInfoDto;
import com.tang.enums.AppHttpCodeEnum;
import com.tang.exception.SystemException;
import com.tang.sys.ResponseResult;
import com.tang.sys.entity.*;
import com.tang.sys.mapper.RoleMapper;
import com.tang.sys.mapper.UserMapper;
import com.tang.sys.mapper.UserRoleMapper;
import com.tang.sys.service.IArticleService;
import com.tang.sys.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tang.sys.vo.*;
import com.tang.utils.BeanCopyUtils;
import com.tang.utils.SecurityUtils;
import javafx.scene.canvas.GraphicsContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author shankaka
 * @since 2023-04-14
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    // 正则表达式匹配中文字符
    private static final String CHINESE_PATTERN = "[\u4e00-\u9fa5]";
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Autowired
    private IUserService iUserService;
    @Resource
    private RoleMapper roleMapper;
    @Autowired
    private IArticleService iArticleService;
    @Autowired
    private StringRedisTemplate redisTemplate;


    @Override
    public ResponseResult userInfo() {
        //获取用户当前的id
        Long userId = SecurityUtils.getUserId();
        //根据用户id查询用户信息
        User user = getById(userId);
        //封装成userinfo
        UserInfoVo vo = BeanCopyUtils.copyBean(user, UserInfoVo.class);
        return ResponseResult.okResult(vo);
    }

    @Override
    public ResponseResult updateUserInfo(User user) {
        updateById(user);
        return ResponseResult.okResult();
    }

    //注册
    @Override
    public ResponseResult register(User user) {

        //对数据进行非空判断
        if (!StringUtils.hasText(user.getUserName()) ){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getPassword()) ){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getNickName()) ){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getEmail()) ){
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        // 检查用户名是否包含中文字符
        if (containsChineseCharacters(user.getUserName())) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_CONTAINS_CHINESE);
        }

        // 检查密码是否包含中文字符
        if (containsChineseCharacters(user.getPassword())) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_CONTAINS_CHINESE);
        }
        //对数据进行是否存在的判断
        if (userNameExist(user.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        if (userNickNameExist(user.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_EXIST);
        }
        if (emailExist(user.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_EXIST);
        }

        //对密码进行加密
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        // 设置注册时间为当前时间
        user.setCreateTime(new Date());
        // 生成随机的后四位数字
        Random random = new Random();
        int randomInt = random.nextInt(9000) + 1000; // 生成1000到9999之间的随机数

        // 获取当前年份的后两位
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);

        // 组合前四位年份和后四位随机数
        String userUuid = String.format("%04d%04d", year, randomInt);

        // 设置用户UUID
        user.setUserUuid(Integer.valueOf(userUuid));
        //存入数据库
        save(user);
        return ResponseResult.okResult();
    }
    private boolean containsChineseCharacters(String input) {
        Pattern pattern = Pattern.compile(CHINESE_PATTERN);
        Matcher matcher = pattern.matcher(input);
        return matcher.find();
    }

    @Override
    public ResponseResult<PageVo> adminUserList(Integer pageNum, Integer pageSize, UserInfoDto userInfoDto) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(userInfoDto.getUserName()),User::getUserName,userInfoDto.getUserName());
        wrapper.like(StringUtils.hasText(userInfoDto.getNickName()),User::getNickName,userInfoDto.getNickName());
        wrapper.eq(StringUtils.hasText(userInfoDto.getStatus()),User::getStatus,userInfoDto.getStatus());

        Page<User> page = new Page<>();
        page.setCurrent(pageNum);
        page.setSize(pageSize);

        page(page,wrapper);

        PageVo pageVo = new PageVo(page.getRecords(),page.getTotal());

        return ResponseResult.okResult(pageVo);
    }

    @Override
    public void addUserList(User user) {
        //写入角色
        //对数据进行非空判断
        if (!StringUtils.hasText(user.getUserName()) ){
            throw new SystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getPassword()) ){
            throw new SystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getNickName()) ){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getEmail()) ){
            throw new SystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        //对数据进行是否存在的判断
        if (userNameExist(user.getUserName())){
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        if (userNickNameExist(user.getNickName())){
            throw new SystemException(AppHttpCodeEnum.NICKNAME_EXIST);
        }
        if (emailExist(user.getEmail())){
            throw new SystemException(AppHttpCodeEnum.EMAIL_EXIST);
        }
        user.setCreateTime(new Date());
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        this.baseMapper.insert(user);
        //写入角色关系表
        if (null != user.getRoleIds()){
            for (Long roleId : user.getRoleIds()) {
                userRoleMapper.insert(new UserRole(user.getId(), roleId));
            }
        }
    }
    //修改
    @Override
    public ResponseResult getUserById(String id) {
        //查询用户id信息封装vo
        User user = this.baseMapper.selectById(id);
        AdminUserUpdateVo adminUserUpdateVo = BeanCopyUtils.copyBean(user, AdminUserUpdateVo.class);
        //查询所有的角色列表
        LambdaQueryWrapper<Role> wrapper = new LambdaQueryWrapper<>();
        List<Role> roleList = roleMapper.selectList(wrapper);
        //查询用户所关联的角色id列表
        LambdaQueryWrapper<UserRole> userRoleWrapper = new LambdaQueryWrapper<>();
        userRoleWrapper.eq(UserRole::getUserId, id);
        List<UserRole> userRoleList = userRoleMapper.selectList(userRoleWrapper);
        List<Long> roleIdList = userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        return ResponseResult.okResult(new AdminUserRoleVo(roleIdList,roleList,adminUserUpdateVo));
    }

    //删除
    @Override
    public ResponseResult deleteUserById(Long id) {
        //获取用户当前的id
        Long userId = SecurityUtils.getUserId();
        //根据用户id查询用户信息
        if (Objects.equals(userId, id)){
            return ResponseResult.errorResult(AppHttpCodeEnum.valueOf("不能删除当前登录用户"));
        }
        this.baseMapper.deleteById(id);
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,id);
        userRoleMapper.delete(wrapper);
        return ResponseResult.okResult(wrapper);
    }
    //实现修改和角色添加
    @Override
    public ResponseResult UpdateUserById(User user) {
        //更新角色表
        this.baseMapper.updateById(user);
        //删除原有的角色
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,user.getId());
        userRoleMapper.delete(wrapper);
        //新增角色
        if (null != user.getRoleIds()){
            for (Long roleId : user.getRoleIds()) {
                userRoleMapper.insert(new UserRole(user.getId(),roleId));
            }
        }

        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult UserInfo() {
        //获取当前登录的用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long id1 = loginUser.getUser().getId();

        User byId = iUserService.getById(id1);

        String userName = byId.getUserName();
        String nickName = byId.getNickName();
        Long id = byId.getId();
        // 查询用户所属的角色列表
        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId,id);
        List<UserRole> userRoleList = userRoleMapper.selectList(wrapper);

        List<Long> roleIdList = new ArrayList<>();
        for (UserRole userRole : userRoleList) {
            roleIdList.add(userRole.getRoleId());
        }

        // 查询角色名字列表
        List<String> roleNameList = new ArrayList<>();
        if (roleIdList.size() > 0){
            LambdaQueryWrapper<Role> roleWrapper = new LambdaQueryWrapper<>();
            roleWrapper.in(Role::getId, roleIdList);
            List<Role> roleList = roleMapper.selectList(roleWrapper);
            for (Role role : roleList) {
                roleNameList.add(role.getRoleName());
            }
        }

        String avatar = byId.getAvatar();
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("id", id1.toString());
        userInfo.put("userName", userName);
        userInfo.put("nickName", nickName);
        userInfo.put("avatar", avatar);
        userInfo.put("roles", roleNameList);

        return ResponseResult.okResult(userInfo);
    }
    //找回密码
    @Override
    public ResponseResult handpassword(User user) {
        //先判断用户名是否存在
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserName,user.getUserName());
        wrapper.eq(User::getEmail,user.getEmail());
        User existUser = iUserService.getOne(wrapper);

        if (existUser == null){
            // 用户名或邮箱不存在，返回相应提示信息
            return ResponseResult.errorResult(AppHttpCodeEnum.USER_EMAIL);
        }


        // 更新用户密码
        existUser.setPassword(user.getPassword()); //这里假设新密码存放在 User 对象的 password 字段中

        // 对用户新密码进行加密
        String encodePassword = passwordEncoder.encode(user.getPassword());
        existUser.setPassword(encodePassword);
        iUserService.updateById(existUser);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS_PASSWORD);
    }

    @Override
    public ResponseResult talkUser() {
        //获取当前登录的用户
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long id1 = loginUser.getUser().getId();

        User byId = iUserService.getById(id1);

        String userName = byId.getUserName();
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("userName", userName);
        return ResponseResult.okResult(userInfo);
    }

    @Override
    public ResponseResult<UserVo> updateStatus(UserVo userVo) {
        User user = userMapper.selectById(userVo.getUserId());
        user.setStatus(userVo.getStatus());
        userMapper.updateById(user);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult addUserExp(User userexp) {
        // 获取当前时间
        Date currentTime = new Date();

        //获取用户当前的id
        Long userId = SecurityUtils.getUserId();
        //根据用户id查询用户信息
        User user = getById(userId);
        // 获取上次签到时间
        Date lastSignInTime = user.getSigntime();


        // 如果上次签到时间为空或者距离上次签到时间已经超过一天
        if (lastSignInTime == null || isOverOneDay(lastSignInTime, currentTime)) {
            String userExp1 = user.getUserExp();

            // 将经验值转换为整数，如果它是字符串类型
            int currentExp = 0;
            if (userExp1 != null && !userExp1.isEmpty()) {
                try {
                    currentExp = Integer.parseInt(userExp1);
                } catch (NumberFormatException e) {
                    // 处理无效经验值的情况
                    return ResponseResult.errorResult(505, "无效");
                }
            }

            // 检查用户的签到状态
            String userSign = user.getUserSign();
            if ("1".equals(userSign)) {
                // 用户已签到，不再增加经验值和更新签到状态
                return ResponseResult.errorResult(506, "已签到，不能重复签到");
            }

            // 增加 1000 经验值
            int expToAdd = 1000;
            int newExp = currentExp + expToAdd;


            // 更新用户的经验值
            user.setUserExp(String.valueOf(newExp));
            user.setUserSign("1"); // 设置签到状态为已签到
            // 更新VIP等级，每签到一次VIP等级加1
            String currentVipLevel = user.getUserVip();
            int newVipLevel = Integer.parseInt(currentVipLevel) + 1;
            user.setUserVip(String.valueOf(newVipLevel));

            // 更新签到时间
            user.setSigntime(currentTime);
            updateById(user);
            // 调用定时任务或定时器方法，在两分钟后重置签到状态
            scheduleResetSignStatus(user.getId(), 300); // 两分钟后重置签到状态

            return ResponseResult.okResult(200, "签到成功，经验值增加" + expToAdd + "点。");
        } else {
            // 检查如果距离上次签到不足一天，将签到状态设置为未签到
            user.setUserSign("0");
            updateById(user);

            // 一天只能签到一次
            // 将剩余时间返回给前端
            return ResponseResult.errorResult(506, "5分钟只能签到一次");
        }

    }

    //兑换会员
    @Override
    public ResponseResult uservipExchange(User userExchange) {
        //获取用户当前的id
        Long userId = SecurityUtils.getUserId();
        //根据用户id查询用户信息
        User user = getById(userId);
        //先获取当前的积分是否够
        String userExp1 = user.getUserExp();
        //先判断用户点击的是普通会员还是超级会员的返回,普通会员积分是5000，超级会员是15000
        int requiredExp = 5000;
        // 获取用户的总兑换次数
        int totalExchanges = user.getSviptotal(); // 假设从数据库或其他存储中获取
        if (Integer.parseInt(userExp1) >= requiredExp) {
            Date currentExpirationDate = user.getSviptime();
            // 如果会员还未过期，则在当前到期日期上叠加30天
            if (currentExpirationDate != null && currentExpirationDate.after(new Date())) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(currentExpirationDate);
                calendar.add(Calendar.DAY_OF_MONTH, 30);
                currentExpirationDate = calendar.getTime();
            } else {
                // 如果会员已经过期或从未拥有过会员，则从当前时间开始计算30天
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(Calendar.DAY_OF_MONTH, 30);
                currentExpirationDate = calendar.getTime();
            }

            // 用户积分足够，执行兑换会员的逻辑
            int remainingExp = Integer.parseInt(userExp1) - requiredExp;
            user.setUserExp(String.valueOf(remainingExp));
            user.setSviptime(currentExpirationDate); // 设置会员到期日期
            updateById(user);

            // 更新 totalExchanges 的值并保存
            totalExchanges++; // 每次成功兑换后将总兑换次数加1
            user.setSviptotal(totalExchanges);
            updateById(user);
            // 更新usersvip的值
            String usersvip = "1"; // 初始usersvip的值
            if (totalExchanges >= 5) {
                usersvip = "2";
            }
            if (totalExchanges >= 12) {
                usersvip = "3";
            }
            if (totalExchanges >= 20) {
                usersvip = "4";
            }
            user.setUserSvip(usersvip);
            updateById(user);
            return ResponseResult.okResult(200,"兑换成功");
        } else {
            // 用户积分不足，返回错误信息
            return ResponseResult.errorResult(508, "积分不足");
        }


    }

    // 定时任务或定时器方法，在指定延迟后重置签到状态
    private void scheduleResetSignStatus(Long userId, int delaySeconds) {
        TimerTask task = new TimerTask() {
            public void run() {
                // 根据用户id查询用户信息
                User user = getById(userId);
                if (user != null) {
                    user.setUserSign("0"); // 重置签到状态为未签到
                    updateById(user);

                } else {
                    System.out.println("定时任务执行失败，未找到用户信息");
                }
            }
        };

        Timer timer = new Timer();
        timer.schedule(task, delaySeconds * 1000); // 延迟指定秒数后执行任务
    }


    // 辅助方法：检查两个日期之间是否已经过了一天
    private boolean isOverOneDay(Date lastSignInTime, Date currentTime) {
        //long ONE_DAY = 24 * 60 * 60 * 1000; // 一天的毫秒数
        long TWO_MINUTES = 5 * 60 * 1000; // 两分钟的毫秒数
        long lastSignInTimeMillis = lastSignInTime.getTime();
        long currentTimeMillis = currentTime.getTime();
        return currentTimeMillis - lastSignInTimeMillis >= TWO_MINUTES;
    }

    private boolean emailExist(String email) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getEmail,email);
        return count(queryWrapper) > 0;
    }

    private boolean userNickNameExist(String nickName) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getNickName,nickName);
        return count(queryWrapper) > 0;

    }

    private boolean userNameExist(String userName) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName,userName);
        return count(queryWrapper) > 0;
    }
}
